﻿using Aliyun.OSS;
using Aliyun.OSS.Common;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace Enter.Admin.Utils
{
    public class AliyunOss
    {
        public bool Enable { get; set; }
        public string AccessKeyId { get; set; }
        public string AccessKeySecret { get; set; }
        public string Endpoint { get; set; }
        public string BucketName { get; set; }
    }

    // https://help.aliyun.com/document_detail/32085.html?spm=a2c4g.11186623.2.19.401f1028CViiae#concept-32085-zh
    // https://github.com/aliyun/aliyun-oss-csharp-sdk



    public class Upload
    {
        private readonly ILogger<Upload> _logger;
        private readonly AliyunOss _setting;
        private OssClient _client;

        public Upload(ILogger<Upload> logger, IOptionsSnapshot<AliyunOss> setting)
        {
            _logger = logger;
            _setting = setting.Value;
            if (_setting.Enable)
                _client = new OssClient(_setting.Endpoint, _setting.AccessKeyId, _setting.AccessKeySecret);
            // Configuration.GetSection("Aliyun:OSS").Get<AliyunOss>();
        }

        /*
            IOptions<T> //站点启动后，获取到的值永远不变 
            IOptionsSnapshot<T> //站点启动后，每次获取到的值都是配置文件里的最新值 （reloadOnChange:true 必须为true）        
            IOptionsMonitor<T> //站点启动后，如果配置文件有变化会发布事件 （reloadOnChange:true 必须为true）
        */
        private string ReplaceKey(string key) 
        {
            return key.Replace("\\","/");
        }

        // 上传
        public bool PutObject(string key, FileInfo fileInfo)
        {
            if (!_setting.Enable) return false;
            key = this.ReplaceKey(key);
            try
            {
               var result = _client.PutObject(_setting.BucketName, key, fileInfo.FullName);
               return result.HttpStatusCode == HttpStatusCode.OK;
            }
            catch (OssException ex)
            {
                _logger.LogError(ex, "上传OSS异常[{0}] error code: {1}; Error info: {2}. \nRequestID:{3}\tHostID:{4}", key, ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "上传OSS异常[{0}]: {1}", key, ex.Message);
                throw;
            }
        }
        // 下载
        public bool GetObject(string key)
        {
            if (!_setting.Enable) return false;
            key = this.ReplaceKey(key);
            var fileInfo = FileIO.GetFile(key);
            try
            {
                if (System.IO.File.Exists(fileInfo.FullName))
                {
                    try
                    {
                        System.IO.File.Delete(fileInfo.FullName);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "删除文件异常[{0}]: {1}", fileInfo.FullName, ex.Message);
                        return false;
                    }
                }  
               var result = _client.GetObject(_setting.BucketName, key);
               using (var requestStream = result.Content)
               {
                   using (var fs = File.Open(fileInfo.FullName, FileMode.OpenOrCreate))
                   {
                       int length = 4 * 1024;
                       var buf = new byte[length]; 
                       do{
                           length = requestStream.Read(buf, 0, length);
                           fs.Write(buf, 0, length);
                       } while (length != 0);
                   }
               }
                return true;
            }
            catch (OssException ex)
            {
                _logger.LogError(ex, "下载OSS异常[{0}] error code: {1}; Error info: {2}. \nRequestID:{3}\tHostID:{4}", key, ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "下载OSS异常[{0}]: {1}", key, ex.Message);
                throw;
            }
        }
        // 删除        
        public bool DeleteObject(string key)
        {
            if (!_setting.Enable) return false;
            key = this.ReplaceKey(key);
            try
            {
                var result = _client.DeleteObject(_setting.BucketName, key);
                return result.HttpStatusCode == HttpStatusCode.OK;
            }
            catch (OssException ex)
            {
                _logger.LogError(ex, "删除OSS异常[{0}] error code: {1}; Error info: {2}. \nRequestID:{3}\tHostID:{4}", key, ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除OSS异常[{0}]: {1}", key, ex.Message);
                throw;
            }
        }

        // 是否存在
        public bool ObjectExist(string key)
        {
            if (!_setting.Enable) return false;
            key = this.ReplaceKey(key);
            try
            {
                var result = _client.DoesObjectExist(_setting.BucketName, key);
                return result;
            }
            catch (OssException ex)
            {
                _logger.LogError(ex, "判断OSS异常[{0}] error code: {1}; Error info: {2}. \nRequestID:{3}\tHostID:{4}", key, ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "判断OSS异常[{0}]: {1}", key, ex.Message);
                throw;
            }
        }
    }
}
